package com.common.aspect;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

import com.common.annotation.PageSeparate;
import com.common.page.PageContext;
import com.common.page.PageKeyContext;

/**
 * 分页注解切面 检查接口方法上是否有分页注解， 有就标记分页线程变量分页
 * 
 * @author chenlujun
 * @version [版本号, 2014年10月6日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@Aspect
public class PageSeparateAspect {
	// 配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点
	@Pointcut("execution(* com.pac.*.service.impl..*(..))")
	public void aspect() {
	}

	/*
	 * 配置前置通知,使用在方法aspect()上注册的切入点 同时接受JoinPoint切入点对象,可以没有该参数
	 */
	@Before("aspect()")
	public void before(JoinPoint jp) {
		// 获取目标对象上正在执行的方法名
		String methodName = jp.getSignature().getName();
		// 获取到这个类上面的所有方法对象
		Method meths[] = jp.getSignature().getDeclaringType().getMethods();
		for (Method method : meths) {
			// 找到当前执行的方法对象
			if (methodName.equals(method.getName())) {
				// 获取当前执行方法的所有注解（接口层的注解）
				Annotation[] anns = method.getDeclaredAnnotations();
				if (anns.length > 0) {
					for (Annotation ann : anns) {
						// 有分页注解
						if (PageSeparate.class.equals(ann.annotationType())) {
							// 标记分页
							PageContext.getContext().setPagination(
									PageKeyContext.PAGE_KEY_PAGE_SEPARATE_YES);
						}
					}
				} else {
					PageContext.getContext().setPagination(
							PageKeyContext.PAGE_KEY_PAGE_SEPARATE_NO);
				}

			}
		}
	}

	// 配置后置通知,使用在方法aspect()上注册的切入点
	@After("aspect()")
	public void after(JoinPoint jp) {
		PageContext.getContext().setPagination(
				PageKeyContext.PAGE_KEY_PAGE_SEPARATE_NO);
	}

	// 配置环绕通知,使用在方法aspect()上注册的切入点
	@Around("aspect()")
	public Object around(ProceedingJoinPoint pjp) throws Throwable {
		Object o = pjp.proceed();
		return o;
	}

	// 配置后置返回通知,使用在方法aspect()上注册的切入点
	@AfterReturning("aspect()")
	public void afterReturn(JoinPoint jp) {
		PageContext.getContext().setPagination(
				PageKeyContext.PAGE_KEY_PAGE_SEPARATE_NO);
	}

	// 配置抛出异常后通知,使用在方法aspect()上注册的切入点
	@AfterThrowing(pointcut = "aspect()", throwing = "ex")
	public void afterThrow(Exception ex) {
		PageContext.getContext().setPagination(
				PageKeyContext.PAGE_KEY_PAGE_SEPARATE_NO);
	}
}
